package com.hospital.auth.module.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hospital.auth.module.exception.UserServiceException;
import com.hospital.auth.module.exception.enums.UserExpCode;
import com.hospital.auth.module.mapper.TUserMapper;
import com.hospital.auth.module.service.TUserService;
import com.hospital.auth.module.utils.RedisUtils;
import com.hospital.common.dto.auth.module.UserDto;
import com.hospital.common.enums.RoleType;
import com.hospital.common.enums.auth.module.InitFlag;
import com.hospital.common.pojo.TUser;
import com.hospital.common.utils.JwtUtils;
import com.hospital.common.utils.PwdUtils;
import com.hospital.common.vo.auth.module.UserVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.hospital.common.base.interfaces.Const.SESSION_KEY_PREFIX;

@Service
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser> implements TUserService{

    @Autowired
    private TUserMapper tUserMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Override
    public UserVo login(UserDto userDto) {
        if(ObjectUtils.isEmpty(RoleType.getByValue(userDto.getRoleType()))){
            throw new UserServiceException(UserExpCode.ROLE_WRONG);
        }
        TUser user = checkExist(userDto.getAccount());
        checkRoleType(userDto, user);
        try {
            if(!PwdUtils.verifyPassword(userDto.getPassword(), user.getPassword())){
                throw new UserServiceException(UserExpCode.PASSWORD_WRONG);
            }
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("密码验证失败");
        }
        return convert(user);
    }
    private UserVo convert(TUser user){
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);
        Map<String,Object> payload = new HashMap<>();
        payload.put("userId", user.getId());
        payload.put("roleType", user.getRole());
        userVo.setToken(JwtUtils.generateToken(payload));
        redisUtils.set(SESSION_KEY_PREFIX+userVo.getToken(),null, JwtUtils.EXPIRE_MINUTES, TimeUnit.MINUTES);
        return userVo;
    }

    @Override
    public void register(UserDto userDto) {
        checkAlreadyExist(userDto.getAccount());
        if(!userDto.getRoleType().equals(RoleType.PATIENT.value)){
            throw new UserServiceException(UserExpCode.ROLE_WRONG);
        }
        if(!userDto.getPassword().equals(userDto.getConfirmPassword())){
            throw new UserServiceException(UserExpCode.CONFIRM_PASSWORD_WRONG);
        }
        TUser user = new TUser();
        user.setAccount(userDto.getAccount());
        user.setName("患者_"+user.getAccount());
        user.setRole(RoleType.PATIENT.value);
        user.setPhone(userDto.getAccount());
        user.setInit(InitFlag.NONE.value);
        user.setSex(userDto.getSex());
        user.setCreateTime(LocalDateTime.now());
        try {
            user.setPassword(PwdUtils.sha256(userDto.getPassword()));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("密码加密失败");
        }
        if(tUserMapper.insert(user) == 0){
            throw new UserServiceException(UserExpCode.REGISTER_FAILED);
        }
    }

    @Override
    public void logout(String account) {
        checkExist(account);
    }
    private TUser checkExist(String account){
        LambdaQueryWrapper<TUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TUser::getAccount, account);
        TUser user = tUserMapper.selectOne(queryWrapper);
        if(ObjectUtils.isEmpty(user)){
            throw new UserServiceException(UserExpCode.USER_NOT_EXIST);
        }
        return user;
    }
    private void checkAlreadyExist(String account){
        LambdaQueryWrapper<TUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TUser::getAccount, account);
        if(tUserMapper.selectOne(queryWrapper) != null){
            throw new UserServiceException(UserExpCode.USER_ALREADY_EXIST);
        }
    }
    private void checkRoleType(UserDto userDto,TUser user){
        if(!userDto.getRoleType().equals(user.getRole())){
            throw new UserServiceException(UserExpCode.ROLE_WRONG);
        }
    }
}
